// 方法1：统计总错误次数和总正确次数
function countTotals(values, options) {
  const { successValue, errorValue } = options
  let totalErrors = 0
  let totalCorrects = 0

  values.forEach((value, index) => {
    if (value === errorValue) {
      totalErrors += 1
    } else if (value === successValue) {
      totalCorrects += 1
    } else {
      console.warn(`发现非${successValue}或${errorValue}的值: ${value} 在索引 ${index}`)
    }
  })

  return { totalErrors, totalCorrects }
}

// 方法2：统计连续错误段数和连续正确段数
function countStreaks(values, options) {
  const { successValue, errorValue } = options
  let totalErrorStreaks = 0
  let totalCorrectStreaks = 0
  let lastValue = null

  values.forEach((value, index) => {
    if (value === errorValue) {
      if (lastValue !== errorValue) {
        totalErrorStreaks += 1
      }
    } else if (value === successValue) {
      if (lastValue !== successValue) {
        totalCorrectStreaks += 1
      }
    }
    lastValue = value
  })

  return { totalErrorStreaks, totalCorrectStreaks }
}

// 方法3：统计在每次错误之前的正确次数和在每次正确之前的错误次数
function countTransitions(values, options) {
  const { successValue, errorValue } = options
  let sumCorrectBeforeError = 0
  let countCorrectBeforeError = 0
  let sumErrorBeforeCorrect = 0
  let countErrorBeforeCorrect = 0

  let currentErrorStreak = 0
  let currentCorrectStreak = 0

  values.forEach((value, index) => {
    if (value === errorValue) {
      if (currentCorrectStreak > 0) {
        sumCorrectBeforeError += currentCorrectStreak
        countCorrectBeforeError += 1
        currentCorrectStreak = 0
      }
      currentErrorStreak += 1
    } else if (value === successValue) {
      if (currentErrorStreak > 0) {
        sumErrorBeforeCorrect += currentErrorStreak
        countErrorBeforeCorrect += 1
        currentErrorStreak = 0
      }
      currentCorrectStreak += 1
    }
  })

  return {
    sumCorrectBeforeError,
    countCorrectBeforeError,
    sumErrorBeforeCorrect,
    countErrorBeforeCorrect
  }
}

// 方法4：确定当前的连续状态和长度
function getCurrentStreak(values, options) {
  const { errorValue, successName, errorName } = options
  let currentStreakType = null
  let currentStreakLength = 0
  let currentStreakTypeBoolean = null

  if (values.length === 0) {
    return { currentStreakType, currentStreakLength }
  }

  // 从后往前找最后一个连续的段
  const lastValue = values[values.length - 1]
  currentStreakType = lastValue === errorValue ? errorName : successName
  currentStreakTypeBoolean = lastValue !== errorValue
  currentStreakLength = 1

  for (let i = values.length - 2; i >= 0; i--) {
    if (values[i] === lastValue) {
      currentStreakLength += 1
    } else {
      break
    }
  }

  return { currentStreakType, currentStreakTypeBoolean, currentStreakLength }
}

// 方法5：计算平均值
function computeAverages(
  totalErrors,
  totalCorrects,
  totalErrorStreaks,
  totalCorrectStreaks,
  sumCorrectBeforeError,
  countCorrectBeforeError,
  sumErrorBeforeCorrect,
  countErrorBeforeCorrect
) {
  const averageConsecutiveErrors = totalErrorStreaks > 0 ? parseFloat((totalErrors / totalErrorStreaks).toFixed(2)) : 0

  const averageConsecutiveCorrects =
    totalCorrectStreaks > 0 ? parseFloat((totalCorrects / totalCorrectStreaks).toFixed(2)) : 0

  const averageCorrectBeforeError =
    countCorrectBeforeError > 0 ? parseFloat((sumCorrectBeforeError / countCorrectBeforeError).toFixed(2)) : 0

  const averageErrorBeforeCorrect =
    countErrorBeforeCorrect > 0 ? parseFloat((sumErrorBeforeCorrect / countErrorBeforeCorrect).toFixed(2)) : 0

  return {
    averageConsecutiveErrors,
    averageConsecutiveCorrects,
    averageCorrectBeforeError,
    averageErrorBeforeCorrect
  }
}

// 方法6：比较当前连续状态与平均值
function compareStreak(currentStreakType, currentStreakLength, averageCorrectBeforeError, averageErrorBeforeCorrect, options) {
  const { successName, errorName } = options
  let streakComparisonToAverageCorrectBeforeError = null
  let streakComparisonToAverageErrorBeforeCorrect = null

  if (currentStreakType === successName) {
    if (averageCorrectBeforeError > 0) {
      const difference = currentStreakLength - averageCorrectBeforeError
      const sign = difference > 0 ? '+' : ''
      streakComparisonToAverageCorrectBeforeError =
        difference !== 0
          ? `${difference > 0 ? '高于' : '低于'}平均水平 (差距: ${sign}${difference.toFixed(2)})`
          : `等于平均水平 (差距: 0.00)`
    } else {
      streakComparisonToAverageCorrectBeforeError = '无平均水平数据'
    }
  }

  if (currentStreakType === errorName) {
    if (averageErrorBeforeCorrect > 0) {
      const difference = currentStreakLength - averageErrorBeforeCorrect
      const sign = difference > 0 ? '+' : ''
      streakComparisonToAverageErrorBeforeCorrect =
        difference !== 0
          ? `${difference > 0 ? '高于' : '低于'}平均水平 (差距: ${sign}${difference.toFixed(2)})`
          : `等于平均水平 (差距: 0.00)`
    } else {
      streakComparisonToAverageErrorBeforeCorrect = '无平均水平数据'
    }
  }

  return {
    streakComparisonToAverageCorrectBeforeError,
    streakComparisonToAverageErrorBeforeCorrect
  }
}

// 主方法：整合所有计算
function calculateMetrics(values, options) {
  // 方法1：统计总错误次数和总正确次数
  const totals = countTotals(values, options)
  // 方法2：统计连续错误段数和连续正确段数
  const streaks = countStreaks(values, options)
  // 方法3：统计在每次错误之前的正确次数和在每次正确之前的错误次数
  const transitions = countTransitions(values, options)
  // 方法4：确定当前的连续状态和长度
  const currentStreak = getCurrentStreak(values, options)
  // 方法5：计算平均值
  const averages = computeAverages(
    totals.totalErrors,
    totals.totalCorrects,
    streaks.totalErrorStreaks,
    streaks.totalCorrectStreaks,
    transitions.sumCorrectBeforeError,
    transitions.countCorrectBeforeError,
    transitions.sumErrorBeforeCorrect,
    transitions.countErrorBeforeCorrect
  )
  // 方法6：比较当前连续状态与平均值
  const comparisons = compareStreak(
    currentStreak.currentStreakType,
    currentStreak.currentStreakLength,
    averages.averageCorrectBeforeError,
    averages.averageErrorBeforeCorrect,
    options
  )

  return {
    ...averages,
    totalErrors: totals.totalErrors,
    totalCorrects: totals.totalCorrects,
    totalErrorStreaks: streaks.totalErrorStreaks,
    totalCorrectStreaks: streaks.totalCorrectStreaks,
    currentStreakType: currentStreak.currentStreakType,
    currentStreakLength: currentStreak.currentStreakLength,
    streakComparisonToAverageCorrectBeforeError: comparisons.streakComparisonToAverageCorrectBeforeError,
    streakComparisonToAverageErrorBeforeCorrect: comparisons.streakComparisonToAverageErrorBeforeCorrect
  }
}

export const getMetrics = (values, options) => {
  return calculateMetrics(values, options)
}
